package top.blackr.folivora.common.security.auth.impl;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import net.dreamlu.mica.core.utils.BeanUtil;
import org.springframework.stereotype.Service;
import top.blackr.folivora.common.core.constants.CommonConstants;
import top.blackr.folivora.config.ApplicationProperties;
import top.blackr.folivora.common.security.auth.LoginAuthentication;
import top.blackr.folivora.common.security.auth.SecUser;
import top.blackr.folivora.common.security.crud.model.entity.SysUser;
import top.blackr.folivora.common.security.crud.model.vo.SysUserVo;
import top.blackr.folivora.common.security.crud.repository.SysUserRepository;


@Slf4j
@AllArgsConstructor
@Service(CommonConstants.LoginType.WX)
public final class WxLoginServiceImpl extends DefaultLoginService {

    private final SysUserRepository sysUserRepository;
    private final ApplicationProperties.WxPay wxPay;

    @Override
    public SecUser authentication(LoginAuthentication authentication) {
        String code = String.valueOf(authentication.getCredential());
        SysUserVo userInfo = this.loginWx(code);
        if (ObjectUtil.isNull(userInfo)) {
            return null;
        }
        return BeanUtil.copy(userInfo, SecUser.class);
    }

    /**
     * 微信登录
     * <p>
     * {
     * "session_key": "rztjLpvWuKc965eUE1pz0w==",
     * "openid": "o7IuD5eQxZp0hL2Eo3CyWkjnv-V8"
     * }
     *
     * @param code 登录code
     */
    private SysUserVo loginWx(String code) {
        // 微信登录地址
        String wxLogin = "https://api.weixin.qq.com/sns/jscode2session?appid=%s&secret=%s&js_code=%s&grant_type=authorization_code";
        String url = String.format(wxLogin, wxPay.getAppId(), wxPay.getAppSecret(), code);
        String body = HttpRequest.get(url).execute().body();
        if (JSONUtil.isTypeJSON(body)) {
            JSONObject wxLoginInfo = JSONUtil.parseObj(body);
            String errCode = wxLoginInfo.getStr("errcode");
            String openId = wxLoginInfo.getStr("openid");
            String sessionKey = wxLoginInfo.getStr("session_key");
            if (!StrUtil.equals(errCode, "0") && StrUtil.isEmptyIfStr(openId)) {
                String errMsg = wxLoginInfo.getStr("errmsg");
                log.error("微信登录失败：{}", errMsg);
                return null;
            }
            String unionId = wxLoginInfo.getStr("unionid");
            SysUserVo userVo = sysUserRepository.loginForWx(openId);
            // 用户不存在就注册
            if (ObjectUtil.isEmpty(userVo)) {
                // 注册用户
                SysUserVo registerUserVo = new SysUserVo();
                registerUserVo.setWxOpenid(openId);
                registerUserVo.setWxUnionid(unionId);
                boolean registerUserWx = sysUserRepository.registerForWx(registerUserVo);
                if (registerUserWx) {
                    // 查询到缓存
                    userVo = sysUserRepository.loginForWx(openId);
                }
            } else {
                // 更新微信信息
                SysUser sysUser = new SysUser();
                sysUser.setUserId(userVo.getUserId());
                sysUser.setWxOpenid(openId);
                sysUser.setWxUnionid(unionId);
                sysUserRepository.updateCacheById(sysUser);
            }
            userVo.setSessionKey(sessionKey);
            return userVo;
        }
        return null;
    }
}
